home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 November / EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso / earcd / unix / mp14tar.z / mp14tar / mpack / amigapk.c < prev    next >
C/C++ Source or Header  |  1994-06-01  |  10KB  |  268 lines

  1. /* (C) Copyright 1993 by Mike W. Meyer
  2.  *
  3.  * Permission to use, copy, modify, distribute, and sell this software
  4.  * and its documentation for any purpose is hereby granted without
  5.  * fee, provided that the above copyright notice appear in all copies
  6.  * and that both that copyright notice and this permission notice
  7.  * appear in supporting documentation, and that the name of Mike W.
  8.  * Meyer not be used in advertising or publicity pertaining to
  9.  * distribution of the software without specific, written prior
  10.  * permission.  Mike W. Meyer makes no representations about the
  11.  * suitability of this software for any purpose.  It is provided "as
  12.  * is" without express or implied warranty.
  13.  *
  14.  * MIKE W. MEYER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  15.  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  16.  * FITNESS, IN NO EVENT SHALL MIKE W. MEYER BE LIABLE FOR ANY SPECIAL,
  17.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  18.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  19.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
  20.  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  21.  */
  22. #include <exec/types.h>
  23. #include <exec/execbase.h>
  24. #include <dos/dos.h>
  25. #include <libraries/netsupport.h>
  26.  
  27. #ifdef __SASC
  28. #include <proto/exec.h>
  29. #include <proto/dos.h>
  30. #include <proto/netsupport.h>
  31. #else
  32. #include <clib/exec_protos.h>
  33. #include <clib/dos_protos.h>
  34. #include <clib/netsupport_protos.h>
  35. #endif
  36.  
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <string.h>
  40. #include <ctype.h>
  41. #include <errno.h>
  42.  
  43. #include "version.h"
  44. #include "amiga_protos.h"
  45.  
  46. #if defined(__SASC) && (__VERSION__ > 5) && (__REVISION__ > 50)
  47. static const char DOSId[] = "\0$VER: MPack " MPACK_VERSION " " __AMIGADATE__ ;
  48. #else
  49. static const char DOSId[] = "\0$VER: MPack " MPACK_VERSION " (" __DATE__ ")" ;
  50. #endif
  51.  
  52. #define MAXADDRESS 100
  53.  
  54. extern char *myGetConfig(char *, char *);
  55. extern int errno;
  56. extern int optind;
  57. extern char *optarg;
  58. struct NetSupportLibrary *NetSupportBase;
  59.  
  60. #define TEMPLATE "From/A,Dest=Destination/M,-o=To/K,-s=Subject/K,-d=Description/K,-c=Contents/K,-m=SplitSize/K/N,-n=News/S"
  61. enum {
  62.         FROM ,
  63.         DESTINATION ,
  64.         TO ,
  65.         SUBJECT ,
  66.         DESCRIPTION ,
  67.         CONTENTS ,
  68.         SPLITSIZE ,
  69.         NEWS ,
  70.         OPT_COUNT
  71.         } ;
  72.  
  73. #define HELPSTRING "mpack version " MPACK_VERSION "\n\
  74. Pack the given file into a MIME message for sending to a remote machine\n\
  75. by either mail or news. Automatically splits the file into a multi-part\n\
  76. message if it is larger than splitsize. The options are:\n\
  77. From/A                  The file you are going to send.\n\
  78. Dest=Destination/M      One or more electronic mail addresses or newsgroups.\n\
  79.                         May not be used with the To option.\n\
  80. -o=To/K                 A file  to output to. The message will be written to\n\
  81.                         the given file name. If more than one message is\n\
  82.                         needed, this is the base name, and a sequence number\n\
  83.                         is provided as a suffix.\n\
  84. -s=Subject/K            Subject of the mail message or article. Will be put\n\
  85.                         in each message sent, with sequence numbers appended\n\
  86.                         for more than one messages.\n\
  87. -d=Description/K        The name of a file that describes the file being\n\
  88.                         sent. Add more here later, Mike.\n\
  89. -c=Contents/K           Mime content-type field for the file being sent. The\n\
  90.                         default is application/octet-stream (binary data)\n\
  91.                         but some other MIME types will be recognized.\n\
  92. -m=SplitSize/K/N        Maximum size of a single message in bytes. The\n\
  93.                         default is taken from the environment variable\n\
  94.                         SPLITSIZE. If that is not defined, then there is no\n\
  95.                         limit.\n\
  96. -n=News/S               Causes the destinations to be interpreted as\n\
  97.                         newsgroups to be posted to instead of electronic mail\n\
  98.                         addresses. Has no effect if there are no destinations\n\
  99.                         (i.e. - To is used to write to a file).\n"
  100.  
  101. /* The one thing we have to fre by hand */
  102. static struct RDArgs *my_args = NULL, *args = NULL ;
  103.  
  104. /* A simple utilities */
  105. void post(char *, char *) ;
  106. void warn(char *) ;
  107.  
  108. void
  109. FreeSystem(void) {
  110.  
  111.         if (NetSupportBase) {
  112.                 UnLockFiles() ;
  113.                 CloseLibrary((struct Library *) NetSupportBase) ;
  114.                 }
  115.         if (args) FreeArgs(args) ;
  116.         if (my_args) FreeDosObject(DOS_RDARGS, my_args) ;
  117.         }
  118.  
  119. int
  120. main(int argc, char **argv) {
  121.         FILE *infile, *descfile;
  122.         char *p, **pp, *from, *to, *subject, *description, *contents ;
  123.         char *header = NULL ;
  124.         char **destination ;
  125.         long news, count, splitsize = 0 ;
  126.         char buffer[512] ;
  127.         long part, opts[OPT_COUNT] ;
  128.  
  129.         if (!(NetSupportBase = (struct NetSupportLibrary *) OldOpenLibrary(NETSUPPORTNAME)))
  130.                 fprintf(stderr,
  131.                         "No NetSupport.Library: Can't parse configfiles.\n");
  132.  
  133.         onexit(FreeSystem) ;
  134.         memset((char *) opts, 0, sizeof(opts)) ;
  135.         if ((p = myGetConfig("SPLITSIZE", NULL)) && *p >= '0' && *p <= '9')
  136.                 splitsize = atoi(p) ;
  137.  
  138.         opts[SPLITSIZE] = (long) &splitsize ;
  139.  
  140.         if (!(my_args = AllocDosObject(DOS_RDARGS, NULL))) {
  141.                 PrintFault(IoErr(), *argv) ;
  142.                 exit(RETURN_FAIL) ;
  143.                 }
  144.         my_args->RDA_ExtHelp = HELPSTRING ;
  145.         if (!(args = ReadArgs(TEMPLATE, opts, my_args))) {
  146.                 PrintFault(IoErr(), *argv) ;
  147.                 exit(RETURN_FAIL) ;
  148.                 }
  149.  
  150.         from = (char *) opts[FROM] ;
  151.         to = (char *) opts[TO] ;
  152.         subject = (char *) opts[SUBJECT] ;
  153.         description = (char *) opts[DESCRIPTION] ;
  154.         contents = (char *) opts[CONTENTS] ;
  155.         news = opts[NEWS] ;
  156.         splitsize = *((long *) opts[SPLITSIZE]) ;
  157.         destination = (char **) opts[DESTINATION] ;
  158.  
  159.         /* Make sure we can open the description file. */
  160.         if (description) {
  161.                 if (!(descfile = fopen(description, "r"))) {
  162.                         fprintf(stderr, "Can't open the description file \"%s\"!\n", description);
  163.                         exit(RETURN_ERROR) ;
  164.                 }
  165.         }
  166.         else
  167.                 descfile = NULL;
  168.  
  169.         /* Make sure we're sending something reasonable. */
  170.         if (contents) {
  171.                 if (!cistrncmp(contents, "text/", 5)) {
  172.                         fprintf(stderr, "This program is not appropriate for encoding textual data\n") ;
  173.                         exit(RETURN_ERROR) ;
  174.                         }
  175.                 if (cistrncmp(contents, "application/", 12)
  176.                 && cistrncmp(contents, "audio/", 6)
  177.                 && cistrncmp(contents, "image/", 6)
  178.                 && cistrncmp(contents, "video/", 6)) {
  179.                         fprintf(stderr, "Content type must be subtype of application, audio, image, or video\n") ;
  180.                         exit(RETURN_ERROR) ;
  181.                         }
  182.                 }
  183.  
  184.         /* Gotta have something to send! */
  185.         if (!from) {
  186.                 fprintf(stderr, "The From argument is required\n") ;
  187.                 exit(RETURN_ERROR) ;
  188.                 }
  189.  
  190.         /* We must have either To or Destinations, but not both! */
  191.         if (to && destination) {
  192.                 fprintf(stderr, "The To keyword and Destination are mutually exclusive.\n") ;
  193.                 exit(RETURN_ERROR) ;
  194.                 }
  195.         else if (!to && !destination) {
  196.                 fprintf(stderr, "Either a destination or the To keyword is required\n");
  197.                 exit(RETURN_ERROR) ;
  198.                 }
  199.  
  200.         /* And we gotta have a subject! */
  201.         if (!subject) {
  202.                 fputs("Subject: ", stdout) ;
  203.                 fflush(stdout) ;
  204.                 if (!fgets(buffer, sizeof(buffer), stdin)) {
  205.                         fprintf(stderr, "A subject is required\n") ;
  206.                         exit(RETURN_ERROR) ;
  207.                         }
  208.                 if (p = strchr(buffer, '\n')) *p = '\0' ;
  209.                 subject = buffer ;
  210.                 }
  211.  
  212.         /* Build the To: or Newsgroups: line */
  213.         if (destination) {
  214.                 for (count = 25, pp = destination; *pp; pp += 1)
  215.                         count += strlen(*pp) + 3 ;
  216.                 header = xmalloc(count) ;
  217.                 p = stpcpy(header, news ? "Newsgroups: " : "To: ") ;
  218.                 p = stpcpy(p, *destination) ;
  219.                 for (pp = destination + 1; *pp; pp += 1) {
  220.                         p = stpcpy(p, news ? "," : ",\n\t") ;
  221.                         p = stpcpy(p, *pp) ;
  222.                         }
  223.                 stpcpy(p, "\n") ;
  224.                 }
  225.  
  226.         /* Get a name to put the output into */
  227.         if (!to) to = tmpnam(NULL) ;
  228.  
  229.         /* Sigh */
  230.         infile = fopen(from, "r");
  231.         if (!infile) {
  232.                 os_perror(from);
  233.                 exit(1);
  234.                 }
  235.  
  236.         if (encode(infile, (FILE *) 0, from, descfile, subject, header, splitsize, contents, to))
  237.                 exit(RETURN_FAIL) ;
  238.  
  239.         /* Hey, we did it. Now send it if we need to */
  240.         if (destination)
  241.                 if (!access(to, R_OK)) {
  242.                         post(to, news ? POSTNEWS : SENDMAIL) ;
  243.                         remove(to) ;
  244.                         }
  245.                 else
  246.                         for (part = 1;; part += 1) {
  247.                                 sprintf(buffer, "%s.%02d", to, part) ;
  248.                                 if (access(buffer, R_OK)) break ;
  249.                                 post(buffer, news ? POSTNEWS : SENDMAIL) ;
  250.                                 remove(buffer) ;
  251.                                 }
  252.  
  253.         exit(RETURN_OK) ;
  254.         }
  255.  
  256. void
  257. post(char *name, char *command) {
  258.         char *p, buffer[512] ;
  259.  
  260.         sprintf(buffer, "%s < %s", myGetConfig(command, command), name);
  261.         system(buffer) ;
  262.         }
  263.  
  264. void
  265. warn(char *s) {
  266.         abort() ;
  267.         }
  268.